import { orderBy, keyBy, trim, isEmpty } from 'lodash';
// import { Op } from 'sequelize';
import BaseController from './base';
import RoomModel from '../models/room';
import RoomTypeModel from '../models/room-type';
import RoomFloorModel from '../models/room-floor';
import RoomFeatureModel from '../models/room-feature';
import { getSequelize } from '../db';

// order docs https://sequelize.org/docs/v6/core-concepts/model-querying-basics/
class RoomController extends BaseController {
  getModel() {
    return RoomModel;
  }

  getFindWhere(req) {
    const { hotel_id } = req.user;
    const { code, room_type_id } = req.query;
    const where = {
      hotel_id
    };

    if (trim(code)) {
      where.code = { [Op.like]: `%${trim(code)}%` };
    }

    if (room_type_id) {
      where.room_type_id = room_type_id;
    }

    return { where: isEmpty(where) ? undefined : where };
  }

  getInclude() {
    return {
      // attributes: ['id', 'hotel_id', 'code', 'room_type_id', 'room_floor_id', 'max_occupancy', `selectable`, `sequence`, `created_at`, `updated_at`, `version`,],
      include: [{
        model: RoomTypeModel,
        as: 'room_type',
        attributes: ['id', 'code', 'name']
      }, {
        model: RoomFloorModel,
        as: 'room_floor',
        attributes: ['id', 'code', 'name']
      }, {
        model: RoomFeatureModel,
        as: 'features',
        attributes: ['id', 'code', 'name', 'sequence']
      }]
    };
  }

  async postFindAll(data) {
    data.rows.map(row => {
      const features = orderBy(row.features, ['sequence'], ['asc']);
      row.setDataValue('room_feature_ids', features.map(e => e.id));
      row.setDataValue('features', features);
    })
    return data;
  }

  async findOne(req, res, next) {
    try {
      const { id } = req.params;
      const model = this.getModel();
      const data = await model.findOne({
        where: { id },
        include: [{
          model: RoomFeatureModel,
          as: 'features',
          attributes: ['id', 'code', 'name', 'sequence'],
          order: ['sequence', 'ASC']
        }],
        rejectOnEmpty: new Error('数据不存在')
      });

      data.setDataValue('room_feature_ids', orderBy(data.features, ['sequence'], ['asc']).map(e => e.id))
      res.sendOk(data);
    }
    catch (e) {
      next(e);
    }
  }

  async bulkCreate(req, res, next) {
    try {
      const { hotel_id } = req.user;
      const model = this.getModel();
      if (Array.isArray(req.body)) {
        for (const row of req.body) {
          row.hotel_id = hotel_id;
        }

        const transaction = await getSequelize().transaction();

        const roomTypes = await RoomTypeModel.findAll({ where: { hotel_id }, raw: true });
        const roomFeatures = await RoomFeatureModel.findAll({ where: { hotel_id }, raw: true });
        const roomFloors = await RoomFloorModel.findAll({ where: { hotel_id }, raw: true });

        const keyRoomTypes = keyBy(roomTypes, 'code');
        const keyRoomFeatures = keyBy(roomFeatures, 'code');
        const keyRoomFloors = keyBy(roomFloors, 'code');

        const features = {}; // 房号对应的room features;

        for (const row of req.body) {
          row.room_floor_id = keyRoomFloors[row.room_floor_id].id;
          row.room_type_id = keyRoomTypes[row.room_type_id].id;
          features[row.code] = row.room_feature_ids[0].split(',').map(e => keyRoomFeatures[trim(e)].id)
        }

        const result = await model.bulkCreate(req.body, {
          updateOnDuplicate: ['room_type_id', 'room_floor_id', 'max_occupancy', 'selectable', 'disabled', 'sequence'],
          // individualHooks: true,
          transaction,
          req,
          bulk: true,
          features
        });

        await transaction.commit();
        res.sendOk(result);
      } else {
        throw new Error('数据格式错误');
      }
    }
    catch (e) {
      next(e);
    }
  }

}

export default new RoomController();
